﻿#include "FImageView.h"
#include <QWheelEvent>
#include <QMouseEvent>
#include <QScrollBar>
#include <QGraphicsDropShadowEffect>
#include <QStyleOption>
#include <QPainter>

FImageView::FImageView(QWidget *parent)
    : QGraphicsView(parent)
{
    // 场景与 Item
    m_scene = new QGraphicsScene(this);
    setScene(m_scene);

    m_pixmapItem = new QGraphicsPixmapItem();
    m_pixmapItem->setTransformationMode(Qt::SmoothTransformation);
    m_scene->addItem(m_pixmapItem);

    // 隐藏滚动条
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    // 提示与渲染
    setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing);
    setDragMode(QGraphicsView::NoDrag);
    setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);

    // 交互体验
    setTransformationAnchor(QGraphicsView::NoAnchor); // 我们自定义缩放锚点
    setResizeAnchor(QGraphicsView::AnchorViewCenter);
    setMouseTracking(true);

    // 现代化外观：启用半透明背景 & 圆角通过样式表或效果设置
    setAttribute(Qt::WA_StyledBackground, true);
    setStyleSheet("QGraphicsView { background: transparent; border-radius: 12px; }");

    // 可选：轻微阴影（父 widget 可能需要 setAttribute(Qt::WA_TranslucentBackground) 才能更明显）
    auto *effect = new QGraphicsDropShadowEffect(this);
    effect->setBlurRadius(18);
    effect->setOffset(0, 6);
    effect->setColor(QColor(0, 0, 0, 80));
    // setGraphicsEffect(effect);

    updateViewportHints();
}

void FImageView::setImage(const QImage &img, bool autoFit)
{
    setPixmap(QPixmap::fromImage(img));
    if (autoFit) fitToWindow();
}

void FImageView::setPixmap(const QPixmap &pixmap, bool autoFit)
{
    m_pixmapItem->setPixmap(pixmap);
    m_scene->setSceneRect(m_pixmapItem->boundingRect());
    // 重置缩放到 1.0（像素为单位）
    m_currentScale = 1.0;
    resetTransform();
    emit zoomChanged(m_currentScale);
    if (autoFit) fitToWindow();
}

void FImageView::clear()
{
    m_pixmapItem->setPixmap(QPixmap());
    m_scene->setSceneRect(QRectF());
}

void FImageView::setZoom(qreal scale)
{
    if (scale <= 0) return;
    qreal clamped = qBound(m_minScale, scale, m_maxScale);
    qreal factor = clamped / m_currentScale;
    // 以中心点缩放
    applyScale(factor, QPointF(viewport()->width() / 2.0, viewport()->height() / 2.0));
}

void FImageView::setZoomRange(qreal minScale, qreal maxScale)
{
    if (minScale <= 0 || maxScale <= 0 || minScale >= maxScale) return;
    m_minScale = minScale;
    m_maxScale = maxScale;
}

void FImageView::fitToWindow()
{
    if (m_pixmapItem->pixmap().isNull()) return;
    QRectF imgRect = m_pixmapItem->boundingRect();
    QRectF viewRect = viewport()->rect();

    if (imgRect.isEmpty() || viewRect.isEmpty()) return;

    qreal sx = viewRect.width() / imgRect.width();
    qreal sy = viewRect.height() / imgRect.height();
    qreal target = qMin(sx, sy);

    // 设置为目标缩放（以像素为基准）
    m_currentScale = target;
    resetTransform();
    scale(target, target);
    centerOn(m_pixmapItem);
    emit zoomChanged(m_currentScale);
}

void FImageView::wheelEvent(QWheelEvent *event)
{
    if (m_pixmapItem->pixmap().isNull()) {
        QGraphicsView::wheelEvent(event);
        return;
    }

    // 以光标为中心缩放
    QPointF viewPos = event->position();

    // 常见的缩放倍率策略：每“刻度”缩放 1.15 倍
    constexpr qreal stepFactor = 1.15;
    qreal numDegrees = event->angleDelta().y() / 8.0; // Qt 返回的角度
    qreal numSteps = numDegrees / 15.0;
    qreal factor = std::pow(stepFactor, numSteps);

    // 如果按住 Ctrl，则更细腻缩放
    if (event->modifiers() & Qt::ControlModifier) {
        factor = std::pow(1.07, numSteps);
    }

    applyScale(factor, viewPos);
}

void FImageView::applyScale(qreal factor, const QPointF &anchorInView)
{
    qreal newScale = m_currentScale * factor;
    if (newScale < m_minScale) {
        factor = m_minScale / m_currentScale;
        m_currentScale = m_minScale;
    } else if (newScale > m_maxScale) {
        factor = m_maxScale / m_currentScale;
        m_currentScale = m_maxScale;
    } else {
        m_currentScale = newScale;
    }

    // 将视图坐标的锚点映射到场景坐标
    QPointF anchorSceneBefore = mapToScene(QPoint((int)anchorInView.x(), (int)anchorInView.y()));

    // 应用缩放
    scale(factor, factor);

    // 缩放后将锚点保持在相同的视图位置：调整视口中心
    QPointF anchorSceneAfter = mapToScene(QPoint((int)anchorInView.x(), (int)anchorInView.y()));
    QPointF delta = anchorSceneAfter - anchorSceneBefore;
    // 平移使视觉上看起来以锚点缩放
    translate(delta.x(), delta.y());

    emit zoomChanged(m_currentScale);
}

void FImageView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton && !m_pixmapItem->pixmap().isNull()) {
        m_dragging = true;
        m_lastMousePos = event->pos();
        setCursor(Qt::ClosedHandCursor);
        event->accept();
        return;
    }
    QGraphicsView::mousePressEvent(event);
}

void FImageView::mouseMoveEvent(QMouseEvent *event)
{
    if (m_dragging) {
        QPoint delta = event->pos() - m_lastMousePos;
        m_lastMousePos = event->pos();
        // 用滚动条移动视图，避免改变变换矩阵
        horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x());
        verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y());
        event->accept();
        return;
    }

    QGraphicsView::mouseMoveEvent(event);
}

void FImageView::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton && m_dragging) {
        m_dragging = false;
        setCursor(Qt::ArrowCursor);
        event->accept();
        return;
    }
    QGraphicsView::mouseReleaseEvent(event);
}

void FImageView::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    // 双击：切换到适应窗口
    fitToWindow();
}

void FImageView::resizeEvent(QResizeEvent *event)
{
    QGraphicsView::resizeEvent(event);
    // 如果当前是 fitToWindow 的状态（例如刚刚 fit），可以选择保持 fit。这里不强制改变，但如果你想在父窗口改变大小时自动 fit，可以取消注释下面：
    // fitToWindow();
}

void FImageView::updateViewportHints()
{
    // 使背景圆角在视图中可见（需要父 widget 适配）
    setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
